using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using Tiffer;
using Config = Dimok.Config;
using Dimok.Exceptions;

////////////////////////////////////////////////////////////////////////////////////////////////////
// namespace: Dimok.Images
//
// summary:	.
////////////////////////////////////////////////////////////////////////////////////////////////////

namespace Dimok.Images {

	////////////////////////////////////////////////////////////////////////////////////////////////////
	/// <summary>	Image files. </summary>
	///
	/// <remarks>	Dimon, 12/21/2010. </remarks>
	////////////////////////////////////////////////////////////////////////////////////////////////////

	public class ImageFiles {

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Shows the file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="document">	The document. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void ShowFile(string document){ShowFile(Encoding.ASCII.GetBytes(document));}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Shows the file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="document">		The document. </param>
		/// <param name="cotentType">	Type of the cotent. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void ShowFile(string document,string cotentType){ShowFile(Encoding.ASCII.GetBytes(document),cotentType);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Shows the file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="document">	The document. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void ShowFile(byte[] document){ShowFile(document,"");}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Shows the file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="ClientException">	Thrown when client. </exception>
		///
		/// <param name="document">			The document. </param>
		/// <param name="contentType">	Type of the content. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void ShowFile(byte[] document,string contentType){
			HttpResponse Response = HttpContext.Current.Response;
			try{
				if( document == null )
					throw new ClientException("Unknown request.");
				Response.ContentType = contentType.Length > 0 ? contentType : Enums.GetContentType(document);
				Response.Buffer = false;
				Response.BinaryWrite(document);
			}catch(Exception exc){
				ASPException.Publish(exc);
				Response.ContentType = "text/html";
				Response.Write("<pre>"+ClientException.GetMessages(exc)+"</pre>");
			}
		}

		#region Files

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Deletes the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">			Filename of the file. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string DeletePages(string fileName,params int[] pageNumbers){
			fileName = FilePathFull(fileName,"");
			if( !File.Exists(fileName) || new FileInfo(fileName).Length == 0 || FileManager.IsAllPages(pageNumbers) ){
				File.Delete(fileName);
				return fileName;
			}
			try{
				switch( Enums.GetPageType(fileName) ){
					case PageTypes.TIFF: return Tiff.DeletePages(fileName,pageNumbers);
					case PageTypes.PDF : return Documents.PDF.DeletePages(fileName,pageNumbers);
				}
				new Exception("Unknown file type type.");
			}catch(Exception exp) {throw new Exception("\nFileName:"+fileName,exp);}
			return fileName;
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Move pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileFrom">			The file from. </param>
		/// <param name="fileTo">				The file to. </param>
		/// <param name="pageAfter">		The page after. </param>
		/// <param name="copy">					true to copy. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void MovePages(string fileFrom,string fileTo,int pageAfter,bool copy,params int[] pageNumbers){
			fileFrom = FilePathFull(fileFrom);
			fileTo = FilePathFull(fileTo);
			try{
				switch( Enums.GetPageType(fileFrom) ){
					case PageTypes.TIFF:	
						Tiff.MovePages(fileFrom,fileTo,pageAfter,copy,pageNumbers); return;
					case PageTypes.PDF:
						Documents.PDF.MovePages(fileFrom,fileTo,pageAfter,copy,pageNumbers); return;
				}
			}catch(Exception exp) {throw new Exception("\nFileFrom:"+fileFrom+"\nFileTo:"+fileTo,exp);}
			throw new Exception("File "+fileFrom+" is of unknown type.");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Move pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">		Filename of the file. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="pageStart">	The page start. </param>
		/// <param name="count">			Number of. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] MovePages(string fileName,int pageAfter,int pageStart,int count){
			fileName = FilePathFull(fileName);
			try{
				switch( Enums.GetPageType(fileName) ){
					case PageTypes.TIFF:	
						return Tiff.MovePages(FileManager.GetBytesFromFile(fileName),pageAfter-1,pageStart-1,count);
					case PageTypes.PDF:
						Documents.PDF.MovePages(fileName,pageAfter,pageStart,count);
						return null;
				}
			}catch(Exception exp) {throw new Exception("\nFileName:"+fileName,exp);}
			throw new Exception("File "+fileName+" is of unknown type.");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Adds the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="image">			The image. </param>
		/// <param name="fileName">		Filename of the file. </param>
		/// <param name="pageAfter">	The page after. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(byte[] image,string fileName,int pageAfter){//1 - based
			fileName = FilePathFull(fileName);
			try{
				switch( Enums.GetPageType(image) ){
					case PageTypes.TIFF: Tiff.AddPages(image,fileName,pageAfter);	return;
					case PageTypes.PDF : Documents.PDF.AddPages(image,fileName,pageAfter); return;
				}
			}catch(Exception exp) {throw new Exception("\nFileName:"+fileName,exp);}
			throw new Exception("File "+fileName+" is of unknown type.");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Adds the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileTo">			The file to. </param>
		/// <param name="fileFrom">		The file from. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileTo,string fileFrom,int pageAfter,int startPage,int count){//1 - based
			AddPages(fileTo,FileManager.GetBytesFromFile(fileFrom),pageAfter,startPage,count);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Adds the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">		Filename of the file. </param>
		/// <param name="image">			The image. </param>
		/// <param name="pageAfter">	The page after. </param>
		/// <param name="startPage">	The start page. </param>
		/// <param name="count">			Number of. </param>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static void AddPages(string fileName,byte[] image,int pageAfter,int startPage,int count){//1 - based
			fileName = FilePathFull(fileName);
			try{
				switch( Enums.GetPageType(image) ){
					case PageTypes.TIFF:	
						Tiff.AddPages(fileName,image,pageAfter-1,startPage-1,count);
						return;
					case PageTypes.PDF:
						Documents.PDF.AddPages(fileName,image,pageAfter,startPage,count);
						return;
				}
			}catch(Exception exp) {throw new Exception("\nFileName:"+fileName,exp);}
			throw new Exception("File "+fileName+" is of unknown type.");
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	Filename of the file. </param>
		///
		/// <returns>	The pages. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		private static byte[] GetPages(string fileName) {
			return GetPages(fileName,-1);
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Gets the pages. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">			Filename of the file. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	The pages. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[] GetPages(string fileName,params int[] pageNumbers){//1 - based
			try{
				fileName = FilePathFull(fileName);
				switch( Enums.GetPageType(fileName) ){
					case PageTypes.TIFF:	return Tiff.GetPages(fileName,pageNumbers);
					case PageTypes.PDF:		return Documents.PDF.GetPages(fileName,pageNumbers);
					default:throw new Exception("Unknown file type.");
				}
			}catch(Exception exp) {throw new Exception("\nFileName:"+fileName,exp);}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Combines the given file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileNames">		List of names of the files. </param>
		/// <param name="fileOut">			The file out. </param>
		/// <param name="deleteFiles">	true to delete the files. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string Combine(string[] fileNames,string fileOut,bool deleteFiles){
			if( fileNames.Length == 1 ){
				if( fileNames[0].ToLower() != fileOut ){
					if( deleteFiles )File.Move(fileNames[0],fileOut);
					else File.Copy(fileNames[0],fileOut);
				}
				return fileOut;
			}
			switch( Enums.GetPageType(fileNames[0]) ){
				case PageTypes.PDF: return Documents.PDF.CombinePdfs(fileNames,fileOut,deleteFiles);
				default:throw new Exception("Unknown file type.");
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Slices the given file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">			Filename of the file. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[][] Slice(string fileName,params int[] pageNumbers){
			try{
				return Slice(FileManager.GetBytesFromFile(fileName),pageNumbers);
			}catch(Exception exp) {throw new Exception("\nFileName:"+fileName,exp);}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Slices the given file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="pages">				The pages. </param>
		/// <param name="pageNumbers">	A variable-length parameters list containing page numbers. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static byte[][] Slice(byte[] pages,params int[] pageNumbers){
			switch( Enums.GetPageType(pages) ){
				case PageTypes.TIFF: return Tiff.SliceTiff(pages,pageNumbers);
				case PageTypes.PDF: return Documents.PDF.Slice(pages,pageNumbers);
				default:throw new Exception("Unknown file type.");
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Slices the given file. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">	Filename of the file. </param>
		/// <param name="dirOut">		The dir out. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string Slice(string fileName,string dirOut){
			switch( Enums.GetPageType(fileName) ){
				case PageTypes.TIFF: return Tiff.Slice(fileName,dirOut);
				case PageTypes.PDF: return Documents.PDF.Slice(fileName,dirOut);
				default:throw new Exception("Unknown file type.");
			}
		}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	Page count. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="Exception">	Thrown when exception. </exception>
		///
		/// <param name="fileName">	Filename of the file. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static int PageCount(string fileName){
			fileName = FilePathFull(fileName);
			if( !File.Exists(fileName) || new FileInfo(fileName).Length == 0 )return 0;
			switch( Enums.GetPageType(fileName) ){
				case PageTypes.TIFF:	return Tiff.PageCount(fileName);
				case PageTypes.PDF:		return Documents.PDF.PageCount(fileName);
			}
			throw new Exception("File "+fileName+" is of unknown type.");
		}
		#endregion

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	File path full. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <param name="fileName">	Filename of the file. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string FilePathFull(string fileName){return FilePathFull(fileName,null);}

		////////////////////////////////////////////////////////////////////////////////////////////////////
		/// <summary>	File path full. </summary>
		///
		/// <remarks>	Dimon, 12/21/2010. </remarks>
		///
		/// <exception cref="EmptyFileException">	Thrown when emptyfile. </exception>
		///
		/// <param name="fileName">					Filename of the file. </param>
		/// <param name="defaultExtention">	Default extention. </param>
		///
		/// <returns>	. </returns>
		////////////////////////////////////////////////////////////////////////////////////////////////////

		public static string FilePathFull(string fileName,string defaultExtention) {
			if( !Regex.IsMatch(fileName,Config.imaging.WS.ImagePath.Replace("\\","\\\\")) &&
					!Regex.IsMatch(fileName,"[:]\\\\") )
				fileName = Path.Combine(Config.imaging.WS.ImagePath,fileName.Trim());
			if( !File.Exists(fileName) && !Path.HasExtension(fileName) )
				try{fileName = fileName+"."+Enums.GetExtention(fileName);
				}catch(EmptyFileException){
					if( defaultExtention != null )fileName += "."+Regex.Replace(defaultExtention,"^[.]","");
					else throw;
				}
			return fileName;
		}
	}
}
